from contextlib import asynccontextmanager
from pathlib import Path

import dotenv

dotenv.load_dotenv(dotenv_path=".env.dev")

from fastapi import Depends, FastAPI
from fastapi.openapi.utils import get_openapi
from fastapi.staticfiles import StaticFiles
from fastapi_pagination import add_pagination
from tortoise.contrib.fastapi import register_tortoise

from apps.blog.routers import router as blog_router
from apps.blog.search import search_service
from apps.fileserver.routers import router as fileserver_router
from apps.gallery.routers import router as gallery_router
from apps.message.routers import router as message_router
from apps.system.routers import router as system_router
from apps.users.models import User
from apps.users.routers import router as users_router
from config import (
    DEFAULT_ADMIN_NICKNAME,
    DEFAULT_ADMIN_PASSWORD,
    DEFAULT_ADMIN_USERNAME,
    TORTOISE_ORM,
)
from utils.auth import conditional_login_required, get_password_hash
from utils.middleware import setup_middleware_and_exception_handler


@asynccontextmanager
async def lifespan(app: FastAPI):
    # 启动时执行
    await create_default_admin()
    await search_service.rebuild_index()
    yield
    # 关闭时执行
    search_service.delete_index()


app = FastAPI(
    title="blog api",
    description="blog openapi generated by fastapi with swagger ui",
    version="1.0.0",
    dependencies=[Depends(conditional_login_required)],
    lifespan=lifespan,
)


def custom_openapi():
    if app.openapi_schema:
        return app.openapi_schema

    openapi_schema = get_openapi(
        title=app.title,
        version=app.version,
        description=app.description,
        routes=app.routes,
    )

    # 添加自定义的安全方案
    openapi_schema["components"]["securitySchemes"] = {
        "OAuth2PasswordBearer": {
            "type": "oauth2",
            "flows": {"password": {"tokenUrl": "/api/auth/token", "scopes": {}}},
        }
    }

    # 添加全局安全要求
    openapi_schema["security"] = [{"OAuth2PasswordBearer": []}]

    app.openapi_schema = openapi_schema
    return app.openapi_schema


app.openapi = custom_openapi

# 静态文件
Path("static").mkdir(exist_ok=True)
app.mount("/static", StaticFiles(directory="static"), name="static")

# 设置中间件和异常处理
setup_middleware_and_exception_handler(app)

# API 路由
app.include_router(gallery_router, prefix="/api/gallery", tags=["gallery"])
app.include_router(users_router, prefix="/api/auth", tags=["auth"])
app.include_router(blog_router, prefix="/api/blog", tags=["blog"])
app.include_router(fileserver_router, prefix="/api/fileserver", tags=["fileserver"])
app.include_router(message_router, prefix="/api/message", tags=["message"])
app.include_router(system_router, prefix="/api/system", tags=["system"])

# 数据库配置
register_tortoise(
    app,
    config=TORTOISE_ORM,
    generate_schemas=False,
    add_exception_handlers=False,
)

add_pagination(app)


async def create_default_admin():
    admin = await User.get_or_none(username=DEFAULT_ADMIN_USERNAME)
    if not admin:
        hashed_password = get_password_hash(DEFAULT_ADMIN_PASSWORD)
        await User.create(
            username=DEFAULT_ADMIN_USERNAME,
            hashed_password=hashed_password,
            nickname=DEFAULT_ADMIN_NICKNAME,
            active=True,
        )


if __name__ == "__main__":
    import uvicorn

    uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
